package com.xingxue.logistics.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xingxue.logistics.common.vo.RestResult;
import com.xingxue.logistics.common.vo.TreeNode;
import com.xingxue.logistics.common.dto.SysMenu;
import com.xingxue.logistics.common.dto.SysMenuExample;
import com.xingxue.logistics.dao.mapper.SysMenuMapper;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

/**
 * @author Kris at 2018/10/9 10:07
 */
@Service
public class MenuServiceImpl implements MenuService {

    @Autowired
    SysMenuMapper menuMapper;


    @Override
    public List<SysMenu> loadAll() {
        SysMenuExample example = new SysMenuExample();
        example.setOrderByClause(" id asc");
        return menuMapper.selectByExample(example);
    }

    @Override
    public List<TreeNode> createTree(List<SysMenu> menuList) {
        List<TreeNode> treeNodeList = new LinkedList<>();
        for (SysMenu menu : menuList) {
            TreeNode treeNode = new TreeNode(menu.getId(), menu.getParentId(), menu.getName(), menu.getUrl(), null, null);
            treeNodeList.add(treeNode);
        }

        List<TreeNode> result = TreeNode.buildTree(treeNodeList);
        return result;
    }

    @Override
    public PageInfo<SysMenu> searchPage(Integer id, Integer parentId, String menuName, Integer pageNo, Integer pageSize) {
        SysMenuExample example = new SysMenuExample();
        example.setOrderByClause(" id asc");
        SysMenuExample.Criteria criteria = example.createCriteria();
        if (id != null) {
            criteria.andIdEqualTo(id);
        }
        if (parentId != null) {
            criteria.andParentIdEqualTo(parentId);
        }
        if (StringUtils.isNotBlank(menuName)) {
            criteria.andNameLike("%" + menuName + "%");
        }

        //分页控件，调用PageHelper.startPage(pageNo, pageSize);表示分页开始
        PageHelper.startPage(pageNo, pageSize);
        List<SysMenu> sysMenus = menuMapper.selectByExample(example);
        // 通过这句代码，实例化一个页码对象出来。PageInfo<SysMenu> pageInfo = new PageInfo<>(sysMenus);
        PageInfo<SysMenu> pageInfo = new PageInfo<>(sysMenus);
        return pageInfo;
    }


    @Override
    public RestResult add(SysMenu menu) {
        int i = menuMapper.insertSelective(menu);
        if (i > 0) {
            return new RestResult(true, "新增成功", null);
        }
        return new RestResult(false, "新增失败", null);
    }

    @Override
    public RestResult update(SysMenu menu) {
        int i = menuMapper.updateByPrimaryKey(menu);
        if (i > 0) {
            return new RestResult(true, "修改成功", null);
        }
        return new RestResult(false, "修改失败", null);
    }

    @Override
    public RestResult delete(Integer id) {
        int i = menuMapper.deleteByPrimaryKey(id);
        if (i > 0) {
            return new RestResult(true, "删除成功", null);
        }
        return new RestResult(false, "删除失败", null);
    }


    @Override
    public List<SysMenu> treeData(Integer parentId) {
        //1.查询基础数据
        List<SysMenu> baseList = null;
        if (parentId == null) {
            baseList = loadAll();
        } else {
            SysMenuExample example = new SysMenuExample();
            example.setOrderByClause("id asc");
            example.createCriteria().andParentIdEqualTo(parentId);
            baseList = menuMapper.selectByExample(example);
        }
        //2.拼装为树
        return buildTree(baseList);
    }

    @Override
    public List<SysMenu> treeData(Integer parentId, Integer roleId,Integer notJoinRoleId) {
        List<SysMenu> baseList = menuMapper.search(parentId,roleId,notJoinRoleId);
        //2.拼装为树
        return buildTree(baseList);
    }

    /**
     * 构建树形数据
     */
    @Override
    public List<SysMenu> buildTree(List<SysMenu> baseList) {
        //1.找到根节点
        List<SysMenu> rootList = findRoot(baseList);
        //2.循环根节点，并且递归把Children装进去
        for (SysMenu root : rootList) {
            fillChildren(root, baseList);
        }
        return rootList;
    }

    /**
     * 找到根节点 <br/>只要这个树里面没有他的老子，他就是根
     */
    private List<SysMenu> findRoot(List<SysMenu> baseList) {
        //1.找到所有的ID，存入一个集合
        Set<Integer> allIds = new HashSet<>();
        for (SysMenu menu : baseList) {
            allIds.add(menu.getId());
        }
        //2.只要某个菜单的父级ID不存在于第1步的集合中，他就是根
        List<SysMenu> result = new LinkedList<>();
        for (SysMenu menu : baseList) {
            if (!allIds.contains(menu.getParentId())) {
                result.add(menu);
            }
        }
        return result;
    }

    /**
     * 填充下级
     * @param parent
     * @param baseList
     */
    private void fillChildren(SysMenu parent, List<SysMenu> baseList) {
        //1.给自己装孩子
        List<SysMenu> children = screenChildren(parent.getId(), baseList);
        parent.setChildren(children);
        //2.地归去给孩子装孩子
        if (!children.isEmpty()) {
            for (SysMenu menu : children) {
                fillChildren(menu, baseList);
            }
        }
    }




    /**
     * 筛选出孩子节点
     *
     * @param parentId 父级ID
     * @param baseList 基础数据
     */
    private List<SysMenu> screenChildren(Integer parentId, List<SysMenu> baseList) {
        List<SysMenu> result = new LinkedList<>();
        for (SysMenu menu : baseList) {
            if (menu.getParentId().equals(parentId)) {
                result.add(menu);
            }
        }
        return result;
    }
}
